
package src;
import org.geotools.api.data.DataStore;
import org.geotools.api.data.DataStoreFinder;
import org.geotools.api.data.FileDataStore;
import org.geotools.api.data.FileDataStoreFinder;
import org.geotools.api.data.SimpleFeatureSource;
import org.geotools.api.feature.simple.SimpleFeature;
import org.geotools.api.referencing.operation.MathTransform;
import org.geotools.api.referencing.operation.TransformException;
import org.geotools.api.style.Stroke;
import org.geotools.api.style.Style;
import org.geotools.api.style.StyleFactory;
import org.geotools.api.style.Symbolizer;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.NameImpl;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.CRS;
import org.geotools.styling.SLD;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Coordinate;
import org.geotools.api.referencing.FactoryException;
import org.geotools.api.referencing.crs.CoordinateReferenceSystem;
import org.geotools.referencing.CRS;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingNode;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ToolBar;
import javafx.scene.image.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class Lanch extends Application {
    /*
     * 场景
     */
    Scene scene;
    /*
     * 布局类
     */
    AnchorPane anchorPane;//根结点
    AnchorPane anchorPane2;
    /*
     * 有关菜单的类成员
     */
    Menu menuOpen;
    MenuItem menuItemOpenShp;
    MenuItem menuItemOpenImage;
    MenuItem menuItemClose;
    MenuItem menuItemSave;
    Menu menuFile;
    MenuBar menuBar;
    //新增一个工具栏
    ToolBar toolBar;
    /*
     * 记录鼠标的位置
     */
    private double mouseXOffset = 0;
    private double mouseYOffset = 0;
    double startX = 0;
    double startY = 0;
    /*
     * 画图区
     */
    Canvas canvas;//绘制矢量数据的画布
    GraphicsContext gc;//画家
    Image image;//承载栅格数据的对象
    ImageView imageView;

    @Override
    public void start(Stage primaryStage) throws Exception {
        //初始化窗口和场景
        initStage(primaryStage);
        //初始化菜单
        this.setMenu();
        this.initUI();
        this.setToolBar();
    }
    void initStage(Stage stage){   
        this.anchorPane=new AnchorPane();
        // 设置边框样式
        this.anchorPane.setStyle("-fx-border-color: black; -fx-border-width: 1px;");
        stage.getIcons().add(new Image("file:icon.png"));
        this.scene=new Scene(anchorPane);
        stage.setScene(scene);
        stage.setTitle("MyGIs");
        stage.setWidth(1500);
        stage.setHeight(800);
        stage.setResizable(false);
        stage.show();
    }

    void SaveOrOpenFile(){
    FileChooser fileChooser = new FileChooser();
    fileChooser.setInitialFileName("*.shp");
    File file = fileChooser.showOpenDialog(new Stage());
    if (file != null) 
    {
        Platform.runLater(() -> {
         /*将读取的图像路径加载进image，将image添加到ImageView中并设置imageView的一些属性 */
            String fileName = file.toURI().toString();
            if(fileName.toLowerCase().endsWith(".shp"))
                try {
                    loadShapeFile(fileName);
                } catch (FactoryException e) {
                    e.printStackTrace();
                } catch (TransformException e) {
                    e.printStackTrace();
                }
            else{
            loadImage(fileName);
            }
    });
    }
    }
    /*设置菜单的方法 */
    void setMenu(){
        menuOpen=new Menu("打开");
        menuItemOpenShp=new MenuItem("打开shp文件");
        menuItemOpenImage=new MenuItem("打开栅格数据");
        menuOpen.getItems().addAll(menuItemOpenShp,menuItemOpenImage);
        menuItemClose=new MenuItem("关闭");
        menuItemSave=new MenuItem("保存");
        menuItemOpenImage.setOnAction((EventHandler<ActionEvent>) new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
            // AlterFileDirection();
            SaveOrOpenFile();
            }
        });
        menuItemOpenShp.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent arg0) {
               SaveOrOpenFile();
            }
        });
        menuItemSave.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
            // AlterFileDirection();\
            SaveOrOpenFile();
        }
        });
        menuItemClose.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                Platform.exit();
            }
        });
        menuFile=new Menu("文件");
        menuFile.getItems().addAll(menuOpen,menuItemSave,menuItemClose);
        menuBar=new MenuBar();
        menuBar.setStyle("-fx-background-color:#FAEBD7");
        menuBar.getMenus().add(menuFile);
        this.anchorPane.getChildren().addAll(menuBar);
        menuBar.setPrefWidth(anchorPane.getWidth());
        menuBar.setStyle("-fx-background-color: #FAEBD7;" +
                 " -fx-border-color: black;" +
                 " -fx-border-width: 1px;" +
                 " -fx-padding: 5px;" +
                 " -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.5), 5, 0.0, 0, 2);");
        //监听根结点宽度的变化
        this.anchorPane.widthProperty().addListener((observable, oldValue, newValue) -> {
            menuBar.setPrefWidth(newValue.doubleValue());
        });
        
        }
        //设置工具栏
    void setToolBar() {
        toolBar = new ToolBar();
        Button openButton = new Button("打开");
        Button saveButton = new Button("保存");
        Button closeButton = new Button("关闭");

        openButton.setOnAction(event -> SaveOrOpenFile());
        saveButton.setOnAction(event -> SaveOrOpenFile());
        closeButton.setOnAction(event -> Platform.exit());

        toolBar.getItems().addAll(openButton, saveButton, closeButton);
        toolBar.setStyle("-fx-background-color: #D3D3D3;" +
                " -fx-border-color: black;" +
                " -fx-border-width: 1px;" +
                " -fx-padding: 5px;" +
                " -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.5), 5, 0.0, 0, 2);");

        this.anchorPane.getChildren().add(toolBar);
        this.anchorPane.setTopAnchor(toolBar, 30.0); // 菜单栏下方
        this.anchorPane.setLeftAnchor(toolBar, 0.0);
        this.anchorPane.setRightAnchor(toolBar, 0.0);
    }    
    //初始化UI容器布局
    void initUI(){
        //imageView的父容器（根）
        this.anchorPane2=new AnchorPane();
        this.anchorPane2.setStyle("-fx-background-color:#F0FFFF; -fx-border-color: black; -fx-border-width: 1px;");
        //将anchorPane2添加到anchorPane中,并设置其相对位置
        this.anchorPane.getChildren().add(anchorPane2);
        this.anchorPane.setLeftAnchor(anchorPane2,300.0);
        this.anchorPane.setTopAnchor(anchorPane2, 70.0);
        this.anchorPane.setBottomAnchor(anchorPane2, 60.0);
        this.anchorPane.setRightAnchor(anchorPane2, 200.0);
    }
    void loadImage(String fileName){
        image=new Image(fileName);
        imageView=new ImageView(image);
        imageView.setFitWidth(690);
        imageView.setFitHeight(1000);
        imageView.setSmooth(true);
        imageView.setCache(true);
        imageView.setPickOnBounds(true); // 确保图像可以被选中
        imageView.setPreserveRatio(true); // 保持图像比例
        /*创建imageView的父结点布局，将imageView添加到父节点中，并设置其位置 */
        this.anchorPane2.getChildren().add(imageView);  
        this.anchorPane2.setTopAnchor(imageView, 0.0);
        this.anchorPane2.setBottomAnchor(imageView, 0.0);
        this.anchorPane2.setRightAnchor(imageView, 0.0);
        this.anchorPane2.setLeftAnchor(imageView, 0.0);   
        // 创建一个Rectangle作为裁剪区的形状
        Rectangle clipRect = new Rectangle();
        clipRect.widthProperty().bind(anchorPane2.widthProperty());
        clipRect.heightProperty().bind(anchorPane2.heightProperty());
        clipRect.setX(0);
        clipRect.setY(0);
        // 将Clip应用到anchorPane2即imageView的父结点中
        anchorPane2.setClip(clipRect);



       // 监听鼠标滚轮事件实现缩放
       imageView.setOnScroll(e -> {
       double zoomFactor = 1.1;
       if (e.getDeltaY() > 0) {
        imageView.setScaleX(imageView.getScaleX() * zoomFactor);
        imageView.setScaleY(imageView.getScaleY() * zoomFactor);
        }else{
        if(imageView.getScaleX()>=1){
            imageView.setScaleX(imageView.getScaleX() / zoomFactor);
            imageView.setScaleY(imageView.getScaleY() / zoomFactor);
        }
        }
      });
    /*监听鼠标拖动事件实现平移*/
        // 鼠标按下事件，记录起始点坐标
    imageView.setOnMousePressed(event -> {
        mouseXOffset = event.getSceneX();
        mouseYOffset = event.getSceneY();
        imageView.setPickOnBounds(false); // 允许在图片外的区域也能拖动
    });
     // 鼠标按下事件，记录起始点坐标
     imageView.setOnMousePressed(event -> {
         startX = event.getSceneX();
         startY = event.getSceneY();
     });

     // 鼠标拖拽事件，更新图片位置
     imageView.setOnMouseDragged(event -> {
         double deltaX = event.getSceneX() - startX;
         double deltaY = event.getSceneY() - startY;
         imageView.setTranslateX(imageView.getTranslateX() + deltaX);
         imageView.setTranslateY(imageView.getTranslateY() + deltaY);
         startX = event.getSceneX();
         startY = event.getSceneY();
     });
    }
    void loadShapeFile(String fileName) throws FactoryException, TransformException{
        Map<String, Object> map = new HashMap<>();
        map.put("url", fileName);
        try {
            DataStore dataStore = DataStoreFinder.getDataStore(map);
            String typeName = dataStore.getTypeNames()[0];
            SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
            SimpleFeatureCollection featureCollection = featureSource.getFeatures();
           // 获取地理坐标系
           CoordinateReferenceSystem crs = featureSource.getSchema().getCoordinateReferenceSystem();
           if (crs == null) {
            crs = CRS.decode("EPSG:4326");
            System.err.println("CRS信息缺失，已设置默认CRS: " + crs.getName());
           }
           // 为 screenEnvelope 设置一个有效的坐标参考系统
           CoordinateReferenceSystem screenCrs = CRS.decode("EPSG:4326");

          // 定义屏幕坐标系的范围
           ReferencedEnvelope screenEnvelope = new ReferencedEnvelope(0, anchorPane2.getWidth(), 0, anchorPane2.getHeight(), screenCrs);
        
           // 创建坐标转换
           MathTransform transform = CRS.findMathTransform(crs, screenEnvelope.getCoordinateReferenceSystem(), true); 
           if (transform == null) {
            System.err.println("无法创建坐标转换");
            return;
            }  
           try (SimpleFeatureIterator iterator = featureCollection.features()) {
                while (iterator.hasNext()) {
                    SimpleFeature feature = iterator.next();
                    Geometry geometry = (Geometry) feature.getDefaultGeometry();
                  // 获取几何对象的坐标
                   Coordinate[] coordinates = geometry.getCoordinates();
                
                 for (Coordinate coord : coordinates) {
                    double[] geoCoord = {coord.x, coord.y};
                    double[] screenCoord = new double[2];
                    
                    // 进行坐标转换
                    transform.transform(geoCoord, 0, screenCoord, 0, 1);
                    
                    double screenX = screenCoord[0];
                    double screenY = screenCoord[1];
                    
                    // 输出屏幕坐标
                    System.out.println("Feature ID: " + feature.getID());
                    System.out.println("Coordinate: (" + coord.x + ", " + coord.y + ")");
                    System.out.println("Screen Coordinate: (" + screenX + ", " + screenY + ")");          
                 }   
                }
            }
            dataStore.dispose();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


